package org.rcy.framework.utils.validate;


import org.apache.commons.lang3.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ValidateUtils {

	private static final Pattern PATTERN_SMS = Pattern.compile("^SMS_{1}\\w{7,12}$");//TODO 待定 目前长度 11-16位
	private static final Pattern PATTERN_EMAIL = Pattern.compile(
			"^([a-zA-Z0-9_\\-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\\]?)$");
	private static final Pattern PATTERN_VERSION = Pattern.compile("^[0-9]+\\.[0-9]+\\.[0-9]+$");
	private static final Pattern PATTERN_MONEY = Pattern.compile("-?([1-9]+[0-9]*|0)(\\.[\\d]+)?");
	private static final Pattern PATTERN_NUM = Pattern.compile("-?[1-9]+[0-9]*|0");
	private static final Pattern PATTERN_ID = Pattern.compile("(^\\d{15}$)|(^\\d{17}([0-9]|X|x)$)");
	// 中国香港手机号
	private static final Pattern PATTERN_HK_MOBILE = Pattern.compile("^(852 )(5|6|9)\\d{7}$");
	// 中国大陆手机号
	private static final Pattern PATTERN_CHN_MOBILE = Pattern.compile("^(\\+86|86)?1[0-9]{10}$");
	// 中国台湾手机号
	private static final Pattern PATTERN_TPE_MOBILE = Pattern.compile("^(886 )(09|9)\\d{8}$");
	// 中国澳门手机号
	private static final Pattern PATTERN_MO_MOBILE = Pattern.compile("^(853 )6\\d{7}$");
	// 不带区号的中国香港手机号
	private static final Pattern NO_AREA_CODE_HK_MOBILE = Pattern.compile("^(5|6|9)\\d{7}$");
	// 不带区号的中国台湾手机号
	private static final Pattern NO_AREA_CODE_TPE_MOBILE = Pattern.compile("^(09|9)\\d{8}$");
	// 香港身份证号
	private static final Pattern PATTERN_HK_IDCARD = Pattern.compile("^[A-Z]\\d{6}[\\(（][\\dA][\\)）]$");
	//日期
	private static final Pattern HYPHEN_DATE = Pattern.compile(
			"^(?:(?!0000)[0-9]{4}-(?:(?:0?[1-9]|1[0-2])-(?:0?[1-9]|1[0-9]|2[0-8])|(?:0?[13-9]|1[0-2])-(?:29|30)|(?:0?[13578]|1[02])-31)|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-0?2-29)$");
	private static final char NUMBER[]= {'0','1','2','3','4','5','6','7','8','9'};
	private static final char CHINESE[]= {'〇','一','二','三','四','五','六','七','八','九'};
	// 二代身份证
	private static final Pattern PATTERN_CHN_IDCARD = Pattern.compile("[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]");
	private static final Pattern PATTERN_SPECIAL_SYMBOL = Pattern.compile("[`~!@#$%^&*()\\-+=|{}':;',\\[\\].<>/?~！@#￥%……&*（）——+|{}【】‘；：”“’。，、？]");;

	/**
	 * 判断短信模板key格式 
	 * @param smsKey
	 * @return
	 */
	public static boolean isSms(final String smsKey) {
		if (StringUtils.isEmpty(smsKey)) {
			return false;
		}
		Matcher matcher = PATTERN_SMS.matcher(smsKey);
		if (!matcher.matches()) {
			return false;
		}
		return true;
	}

	/**
	 * 判断邮箱格式是否正确
	 * 
	 * @param email
	 * @return
	 */
	public static boolean isEmail(final String email) {
		if (StringUtils.isEmpty(email)) {
			return false;
		}
		Matcher matcher = PATTERN_EMAIL.matcher(email);
		if (!matcher.matches()) {
			return false;
		}
		return true;
	}
	
	/**
	 * 判断手机号码格式是否正确
	 * 
	 * @param mobile
	 * @return
	 */
	public static boolean isMobile(final String mobile) {
		if (StringUtils.isEmpty(mobile)) {
			return false;
		}
		if (!isCHNMobile(mobile) && !isHKMobile(mobile) && !isTPEMobile(mobile) && !isMOMobile(mobile)) {
			return false;
		}
		return true;
	}
	
	/**
	 * 验证香港手机号
	 * @param mobile
	 * @return
	 */
	public static boolean isHKMobile(final String mobile) {
		if(StringUtils.isEmpty(mobile)) {
			return false;
		}
		Matcher m = PATTERN_HK_MOBILE.matcher(mobile);
		return m.matches();
	}
	
	/**
	 * 验证不带区号的香港手机号
	 * 
	 * @param mobile
	 * @return
	 */
	public static boolean isHKMobileWithoutAreaCode(final String mobile) {
		if(StringUtils.isEmpty(mobile)) {
			return false;
		}
		Matcher m = NO_AREA_CODE_HK_MOBILE.matcher(mobile);
		return m.matches();
	}
	
	/**
	 * 验证中国大陆手机号
	 * @param mobile
	 * @return
	 */
	public static boolean isCHNMobile(final String mobile) {
		if(StringUtils.isEmpty(mobile)) {
			return false;
		}
		Matcher m = PATTERN_CHN_MOBILE.matcher(mobile);
		return m.matches();
	}
	
	/**
	 * 验证中华台北手机号
	 * @param mobile
	 * @return
	 */
	public static boolean isTPEMobile(final String mobile) {
		if(StringUtils.isEmpty(mobile)) {
			return false;
		}
		Matcher m = PATTERN_TPE_MOBILE.matcher(mobile);
		return m.matches();
	}
	
	/**
	 * 验证不带区号的中华台北手机号
	 * 
	 * @param mobile
	 * @return
	 */
	public static boolean isTPEMobileWithoutAreaCode(final String mobile) {
		if(StringUtils.isEmpty(mobile)) {
			return false;
		}
		Matcher m = NO_AREA_CODE_TPE_MOBILE.matcher(mobile);
		return m.matches();
	}
	
	/**
	 * 验证中国澳门手机号
	 * @param mobile
	 * @return
	 */
	public static boolean isMOMobile(final String mobile) {
		if(StringUtils.isEmpty(mobile)) {
			return false;
		}
		Matcher m = PATTERN_MO_MOBILE.matcher(mobile);
		return m.matches();
	}
	
	public static boolean isHKIdcard(final String idcard) {
		if (org.apache.commons.lang3.StringUtils.isBlank(idcard)) {
			return false;
		}
		return PATTERN_HK_IDCARD.matcher(idcard).matches();
	}
	
	/**
	 * 判断是不是规定的版本号格式
	 * @param mobile
	 * @return
	 */
	public static boolean isVersion(final String version) {
		if (StringUtils.isEmpty(version)) {
			return false;
		}
		Matcher matcher = PATTERN_VERSION.matcher(version);
		if (!matcher.matches()) {
			return false;
		}
		return true;
	}


	/**
	 * 校验密码格式最少8位，最多16位，至少含有数字，字母，特殊字符中的两种
	 * @param password
	 * @return
	 */
	public static boolean validPW(final String password) {
		String pw = StringUtils.trim(password);
		if (StringUtils.isBlank(pw)) {
			return false;
		}
		if (pw.matches("((?=.*\\d)(?=.*\\D)|(?=.*[a-zA-Z])(?=.*[^a-zA-Z]))^.{8,16}$")) {
			return true;
		}
		return false;
	} 

	/**
	 * 校验时间格式（ yyyy-MM-dd）
	 * @param date
	 * @return
	 */
	public static boolean validDate(final String date){
		if (StringUtils.isEmpty(date)) {
			return false;
		}
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
		try {
			Date newDate = format.parse(date);
			Calendar cal=Calendar.getInstance();
			cal.setTime(newDate);  
			Integer year = cal.get(Calendar.YEAR);
			Integer month = cal.get(Calendar.MONTH)+1;
			Integer day = cal.get(Calendar.DAY_OF_MONTH);
			String[] dateArr = date.split("-");
			return  year.equals(Integer.parseInt(dateArr[0]))&&month.equals(Integer.parseInt(dateArr[1]))&&day.equals(Integer.parseInt(dateArr[2]));
		} catch (ParseException e) {
			return false;
		}
		
	}

	/**
	 * 校验金额
	 * @param money
	 * @return
	 */
	public static boolean validMoney(final String money){
		if (StringUtils.isEmpty(money)) {
			return false;
		}
		Matcher matcher = PATTERN_MONEY.matcher(money);
		if (!matcher.matches()) {
			return false;
		}
		return true;
	}
	
	/**
	 * 校验整数
	 * @param num
	 * @return
	 */
	public static boolean validNum(final String num){
		if (StringUtils.isEmpty(num)) {
			return false;
		}
		Matcher matcher = PATTERN_NUM.matcher(num);
		if (!matcher.matches()) {
			return false;
		}
		return true;
	}
	/**
	 * 校验身份证
	 * @param id
	 * @return
	 */
	public static boolean validId(final String id){
		if (StringUtils.isEmpty(id)) {
			return false;
		}
		Matcher matcher = PATTERN_ID.matcher(id);
		if (!matcher.matches()) {
			return false;
		}
		return true;
	}
	
	/**
	 * 校验是否为二代身份证（只校验基本格式）
	 * 
	 * @param idNo 需要校验的身份证号
	 * @return boolean
	 */
	public static boolean isCHNIdNo(String idNo) {
		if (idNo == null || idNo.length() != 18) {
			return false;
		}
		Matcher matcher = PATTERN_CHN_IDCARD.matcher(idNo);
		return matcher.matches();
	}
	
	public static boolean containsSpecilaSymbol(String str) {
		if(str == null || str.length() == 0) {
			return false;
		}
		char[] charArray = str.toCharArray();
		for (int i = 0; i<str.length(); i++) {
			Matcher matcher = PATTERN_SPECIAL_SYMBOL.matcher(String.valueOf(charArray[i]));
			if(matcher.matches()) {
				return true;
			}
		}
		return false;
	}
	
	/**
	 * 根据身份证号解析性别
	 * @param id
	 * @return
	 */
	public static String sex(final String id){
		if(!validId(id)){
			return null;
		}
		String lastValue = "";
		if(id.length()==15){
			lastValue = id.substring(14, 15);
		}
		if(id.length()==18){
			lastValue = id.substring(16, 17);
		}
		if(StringUtils.isNoneBlank(lastValue)){
			return Integer.parseInt(lastValue)%2==0?"女":"男";
		}
		return null;
	}
	
	/**
	 * 验证yyyy-MM-dd格式日期
	 * @param date
	 * @return
	 */
	public static boolean validHyphenDate(final String date) {
		if (StringUtils.isEmpty(date)) {
			return false;
		}
		Matcher matcher = HYPHEN_DATE.matcher(date);
		return matcher.matches();
	}
	
	/**
	 * 验证yyyy/MM/dd格式日期
	 * @param date
	 * @return
	 */
	public static boolean validSlashDate(final String date){
        if(StringUtils.isEmpty(date)) {
        	return false;
        }
        String hyphenDate = date.replace("/", "-");
        return validHyphenDate(hyphenDate);
    }
	
	/**
	 * 验证yyyy年MM月dd日格式日期
	 * @param date
	 * @return
	 */
	public static boolean validChineseDate(final String date) {
		if (StringUtils.isEmpty(date)) {
			return false;
		}
		if (!date.contains("年") || !date.contains("月") || !date.contains("日") || !date.endsWith("日")) {
			return false;
		}
		String hyphenDate = date.replace("年", "-").replace("月", "-").replace("日", "");
		return validHyphenDate(hyphenDate);
	}
	
	/**
	 * 验证全中文格式日期 二〇一九年一月一日
	 * @param date
	 * @return
	 */
	public static boolean validAllChineseDate(final String date) {
		if (StringUtils.isEmpty(date)) {
			return false;
		}
		if (!date.contains("年") || !date.contains("月") || !date.contains("日") || !date.endsWith("日")) {
			return false;
		}
		int yearPos = date.indexOf("年");
		int monthPos = date.indexOf("月");
		String cnYear = date.substring(0, yearPos);
		String cnMonth = date.substring(yearPos + 1, monthPos);
		String cnDay = date.substring(monthPos + 1, date.length() - 1);
		String year = ConvertCnYear(cnYear);
		String month = ConvertCnDateNumber(cnMonth);
		String day = ConvertCnDateNumber(cnDay);
		String numberDate = year + "-" + month + "-" + day;
		return validHyphenDate(numberDate);
	}
	private static String ConvertCnYear(String cnYear) {
		if(cnYear.length() == 2)
			return "20" + ConvertCnNumberChar(cnYear);
		else
			return ConvertCnNumberChar(cnYear);
	}
	private static String ConvertCnNumberChar(String cnNumberStr) {
		String ALL_CN_NUMBER = "〇一二三四五六七八九";
		String ALL_NUMBER = "0123456789";
		StringBuffer buf = new StringBuffer();
		for (int i = 0; i < cnNumberStr.length(); i++) {
			char c = cnNumberStr.charAt(i);
			int index = ALL_CN_NUMBER.indexOf(c);
			if (index != -1) {
				buf.append(ALL_NUMBER.charAt(index));
			} else {
				// buf.append(cnNumberStr.charAt(i));
				buf.append("#");
			}
		}
		return buf.toString();
	}
	private static String ConvertCnDateNumber(String cnNumber) {
		if (cnNumber.length() == 1) {
			if(cnNumber.equals("十"))
				return "10";
			else
				return ConvertCnNumberChar(cnNumber);
		} else if (cnNumber.length() == 2) {
			if (cnNumber.startsWith("十")) {
				return "1" + ConvertCnNumberChar(cnNumber.substring(1, 2));
			} else if (cnNumber.endsWith("十")) {
				return ConvertCnNumberChar(cnNumber.substring(0, 1)) + "0";
			} else {
				return ConvertCnNumberChar(cnNumber);
			}
		} else if (cnNumber.length() == 3) {
			return ConvertCnNumberChar(cnNumber.substring(0, 1) + cnNumber.substring(2, 3));
		}
		return null;
	}
	/**
	 * 获取数字格式
	 * @param chinese
	 * @return
	 */
	private static String getNumberDate(String strChinese) {
		if(StringUtils.isEmpty(strChinese)) {
			return null;
		}
		char chinese[] = strChinese.toCharArray();
		char[] numberDate = new char[chinese.length];
		for(int i=0;i<chinese.length;i++) {
			int positon=-1;
			for(int j=0;j<CHINESE.length;j++) {
				if(CHINESE[j]==chinese[i]) {
					positon = j;
					break;
				}
			}
			if (positon == -1) {
				return null;
			}
			numberDate[i]=NUMBER[positon];
		}
		return String.valueOf(numberDate);
	}
	
	/**
	 * 校验是否包含中文
	 * @param str
	 * @return
	 */
	public static boolean isContainChinese(String str) {
		Pattern p = Pattern.compile("[\u4e00-\u9fa5]");
		Matcher m = p.matcher(str);
		if (m.find()) {
			return true;
		}
		return false;
	}
	
	/**
	 * 校验是否包含数字
	 * @param str
	 * @return
	 */
	public static boolean isContainNum(String str) {
		Pattern p = Pattern.compile(".*[0-9].*");
		Matcher m = p.matcher(str);
		if (m.find()) {
			return true;
		}
		return false;
	}

	/**
	 * 将中国大陆手机号设为标准11位阿拉伯数字，港澳台手机号设为：区号+空格+手机号（852 96660000）
	 * @param mobile
	 * @return
	 */
	public static String reviseMobile(final String mobile) {
		if (StringUtils.isBlank(mobile)) {
			return mobile;
		} else {
			String revisedMobile = mobile.replaceAll("\\s|-|\\+|/", "");
			if (revisedMobile.length() > 3) {
				if (revisedMobile.startsWith("86")) {
					revisedMobile = revisedMobile.substring(2);
				} else if (revisedMobile.startsWith("852") || revisedMobile.startsWith("886") || revisedMobile.startsWith("853")) {
					revisedMobile = revisedMobile.substring(0, 3) + " " + revisedMobile.substring(3);
				}
			}
			return revisedMobile;
		}
	}
	
	
	public static boolean isMobile(final String mobile, Boolean checkIntl) {
		if (checkIntl != null && checkIntl) {
			return isMobile(mobile) || isIntlMobile(mobile);
		}
		return isMobile(mobile);
	}

	/**
	 * 判断手机号码格式是为国际手机号
	 *
	 * @param mobile
	 * @return
	 */
	public static boolean isIntlMobile(final String mobile) {
		try {
			if (StringUtils.isEmpty(mobile)) {
				return false;
			}
			if (MobileRegularExp.isIntlSms(mobile)) {
				String nationalCode = mobile.substring(0, mobile.indexOf(StringUtils.SPACE));
				String mobileNumber = mobile.substring(mobile.indexOf(StringUtils.SPACE) + 1);
						return MobileRegularExp.isMobileNumber(nationalCode, mobileNumber);
			}
		} catch (Exception e) {
			return false;
		}
		return false;
	}
	
}